# -*- coding: utf-8 -*-
import os

import manim

class Main(manim.Scene):
    def construct(self):
        self.add_sound("back.ogg")
        self.wait()
        Q1 = manim.Text("Q: 什么是bcd码?").set_color(manim.BLUE)
        self.play(manim.Write(Q1))

        Q1.generate_target()
        Q1.target.shift(3 * manim.UP + 4 * manim.LEFT)
        self.play(manim.MoveToTarget(Q1))
        A1 = manim.Text("A: bcd码, 即用四位二进制来表示十进制").set_color(manim.GREEN)
        A1.shift(2 * manim.UP + 1 * manim.LEFT)
        self.play(manim.Write(A1))
        self.wait(2)
        self.play(manim.FadeOut(Q1), manim.FadeOut(A1))

        example = manim.Text("例如: 十进制   bcd码").set_x(-3).set_y(3)
        example1 = manim.Text("     9   -> 0000 1001").set_x(-3).set_y(2)
        example2 = manim.Text("     16   -> 0001 0110").set_x(-3).set_y(1)
        example3 = manim.Text("     10   -> 0001 0000").set_x(-3).set_y(0)
        example4 = manim.Text("   225 -> 0010 0010 0101").set_x(-2).set_y(-1)
        self.play(manim.Write(example),
                  manim.Write(example1),
                  manim.Write(example2),
                  manim.Write(example3),
                  manim.Write(example4))
        self.wait(5)
        self.play(manim.FadeOut(example),
                  manim.FadeOut(example1),
                  manim.FadeOut(example2),
                  manim.FadeOut(example3),
                  manim.FadeOut(example4))

        Q2 = manim.Text("那么我们如何将任意二进制数据都转换为bcd码呢?") \
            .set_color(manim.BLUE) \
            .set_x(0).set_y(2)
        A2 = manim.Text("一个非常简单直观的方法是使用加法:",
                        color=manim.GREEN,
                        t2c = {"简单直观": "red"}) \
            .set_x(-1).set_y(1)
        self.play(manim.Write(Q2))
        self.play(manim.Write(A2))
        self.wait()
        really = manim.Text("?").set_x(-2)
        self.play(manim.Write(really))
        self.wait(1.5)
        self.play(manim.FadeOut(Q2), manim.FadeOut(A2), manim.FadeOut(really))

        T1 = manim.Text("进行加法的朴素思考是逢10加6\n"
                        "或者说对数字进行左移\n"
                        "每四位进行分割\n"
                        "若分割块在10~15\n"
                        "或更高位的块为奇数则对该块加6")
        T2 = manim.Text("好抽象, 但我会给三个例子来解释").set_y(-2)
        self.play(manim.Write(T1))
        self.play(manim.Write(T2))
        self.wait(3)
        self.play(manim.FadeOut(T1), manim.FadeOut(T2))

        squares: list = [manim.Square(side_length=1)
                            .shift((i - 3) * manim.LEFT + 3 * manim.UP)
                         for i in range(10)]

        for square in squares[:4]:
            square.set_fill(manim.GREEN, opacity=0.5)
        for surface in squares[4:8]:
            surface.set_fill(manim.YELLOW, opacity=0.5)
        squares[8].set_fill(manim.RED, opacity=0.5)
        squares[9].set_fill(manim.RED, opacity=0.5)

        self.play(*[manim.Create(square) for square in squares])
        self.wait()

        example1_text = manim.Text("Example 1", font="Consolas").set_x(-3).set_y(1)
        num1 = [
            manim.Integer(1).shift(0 * manim.LEFT + 3 * manim.UP),
            manim.Integer(0).shift(-1 * manim.LEFT + 3 * manim.UP),
            manim.Integer(1).shift(-2 * manim.LEFT + 3 * manim.UP),
            manim.Integer(0).shift(-3 * manim.LEFT + 3 * manim.UP),
        ]

        plus = manim.Text("+").shift(1 * manim.LEFT + 2 * manim.UP)
        plus2 = manim.Text("+").shift(5 * manim.LEFT + 2 * manim.UP)
        add1 = [
            manim.Integer(0).shift(0 * manim.LEFT + 2 * manim.UP),
            manim.Integer(1).shift(-1 * manim.LEFT + 2 * manim.UP),
            manim.Integer(1).shift(-2 * manim.LEFT + 2 * manim.UP),
            manim.Integer(0).shift(-3 * manim.LEFT + 2 * manim.UP),
        ]
        add2 = [
            manim.Integer(0).shift(4 * manim.LEFT + 2 * manim.UP),
            manim.Integer(1).shift(3 * manim.LEFT + 2 * manim.UP),
            manim.Integer(1).shift(2 * manim.LEFT + 2 * manim.UP),
            manim.Integer(0).shift(1 * manim.LEFT + 2 * manim.UP),
        ]

        self.play(manim.Write(example1_text))
        self.play(*[manim.Create(num) for num in num1])
        for num in num1:
            num.generate_target()
            num.target.shift(3 * manim.RIGHT)
        self.play(*[manim.MoveToTarget(num) for num in num1])
        for _ in range(3):
            for num in num1:
                num.generate_target()
                num.target.shift(1 * manim.LEFT)
            self.play(*[manim.MoveToTarget(num) for num in num1])
        self.play(manim.Write(plus), *[manim.Create(num) for num in add1])
        self.wait()
        self.play(*[manim.FadeOut(num) for num in num1])

        end1 = [
            manim.Integer(1).shift(1 * manim.LEFT + 3 * manim.UP),
            manim.Integer(0).shift(0 * manim.LEFT + 3 * manim.UP),
            manim.Integer(0).shift(-1 * manim.LEFT + 3 * manim.UP),
            manim.Integer(0).shift(-2 * manim.LEFT + 3 * manim.UP),
            manim.Integer(0).shift(-3 * manim.LEFT + 3 * manim.UP),
        ]

        self.play(*[manim.Create(num) for num in end1],
                  manim.FadeOut(plus),
                  *[manim.FadeOut(num) for num in add1])
        self.wait()
        self.play(*[manim.FadeOut(num) for num in end1],
                  manim.FadeOut(example1_text))

        example2_text = manim.Text("Example 2", font="Consolas").set_x(-3).set_y(1)
        num2 = [
            manim.Integer(1).shift(1 * manim.LEFT + 3 * manim.UP),
            manim.Integer(0).shift(0 * manim.LEFT + 3 * manim.UP),
            manim.Integer(0).shift(-1 * manim.LEFT + 3 * manim.UP),
            manim.Integer(0).shift(-2 * manim.LEFT + 3 * manim.UP),
            manim.Integer(0).shift(-3 * manim.LEFT + 3 * manim.UP),
        ]

        self.play(manim.Write(example2_text))
        self.play(*[manim.Create(i) for i in num2])
        for num in num2:
            num.generate_target()
            num.target.shift(4 * manim.RIGHT)
        self.play(*[manim.MoveToTarget(num) for num in num2])
        for _ in range(4):
            for num in num2:
                num.generate_target()
                num.target.shift(1 * manim.LEFT)
            self.play(*[manim.MoveToTarget(num) for num in num2])
        self.play(manim.Write(plus), *[manim.Create(i) for i in add1])
        self.wait()
        self.play(*[manim.FadeOut(num) for num in num2])

        end2 = [
            manim.Integer(1).shift(1 * manim.LEFT + 3 * manim.UP),
            manim.Integer(0).shift(0 * manim.LEFT + 3 * manim.UP),
            manim.Integer(1).shift(-1 * manim.LEFT + 3 * manim.UP),
            manim.Integer(1).shift(-2 * manim.LEFT + 3 * manim.UP),
            manim.Integer(0).shift(-3 * manim.LEFT + 3 * manim.UP),
        ]
        self.play(*[manim.Create(num) for num in end2],
                  *[manim.FadeOut(num) for num in add1],
                  manim.FadeOut(plus))
        self.wait()
        self.play(manim.FadeOut(example2_text),
                  *[manim.FadeOut(num) for num in end2])

        example3_text = manim.Text("Example 3", font="Consolas").set_x(-3).set_y(1)
        num3 = [
            manim.Integer(1).shift(4 * manim.LEFT + 3 * manim.UP),
            manim.Integer(1).shift(3 * manim.LEFT + 3 * manim.UP),
            manim.Integer(1).shift(2 * manim.LEFT + 3 * manim.UP),
            manim.Integer(1).shift(1 * manim.LEFT + 3 * manim.UP),
            manim.Integer(1).shift(0 * manim.LEFT + 3 * manim.UP),
            manim.Integer(1).shift(-1 * manim.LEFT + 3 * manim.UP),
            manim.Integer(1).shift(-2 * manim.LEFT + 3 * manim.UP),
            manim.Integer(1).shift(-3 * manim.LEFT + 3 * manim.UP),
        ]

        self.play(manim.Write(example3_text))
        self.play(*[manim.Create(num) for num in num3])
        self.wait()
        what_is_this = manim.Text("???")
        self.play(manim.Write(what_is_this))
        self.wait()
        self.play(manim.FadeOut(what_is_this))

        for num in num3:
            num.generate_target()
            num.target.shift(manim.RIGHT * 7)
        self.play(*[manim.MoveToTarget(num) for num in num3])
        self.wait()

        for _ in range(3):
            for num in num3:
                num.generate_target()
                num.target.shift(manim.LEFT)
            self.play(*[manim.MoveToTarget(num) for num in num3])
        self.wait()

        self.play(manim.Write(plus), *[manim.Write(num) for num in add1])
        self.wait()
        self.play(manim.FadeOut(num3[0]), manim.FadeOut(num3[2]))
        num3[0] = manim.Integer(0).shift(0 * manim.LEFT + 3 * manim.UP)
        num3[2] = manim.Integer(0).shift(-2 * manim.LEFT + 3 * manim.UP)
        num3.insert(0, manim.Integer(1).shift(1 * manim.LEFT + 3 * manim.UP))
        self.play(manim.FadeIn(num3[0]),
                  manim.FadeIn(num3[1]),
                  manim.FadeIn(num3[3]),
                  manim.FadeOut(plus),
                  *[manim.FadeOut(num) for num in add1])

        for num in num3:
            num.generate_target()
            num.target.shift(manim.LEFT)
        self.play(*[manim.MoveToTarget(num) for num in num3])
        self.wait()

        self.play(manim.FadeIn(plus), *[manim.Write(num) for num in add1])
        self.wait()
        self.play(*[manim.FadeOut(num3[i]) for i in (1, 2, 4)])
        num3[1] = manim.Integer(1).shift(1 * manim.LEFT + 3 * manim.UP)
        num3[2] = manim.Integer(0).shift(0 * manim.LEFT + 3 * manim.UP)
        num3[4] = manim.Integer(0).shift(-2 * manim.LEFT + 3 * manim.UP)
        self.play(*[manim.FadeIn(num3[i]) for i in (1, 2, 4)],
                  manim.FadeOut(plus),
                  *[manim.FadeOut(num) for num in add1])

        for _ in range(2):
            for num in num3:
                num.generate_target()
                num.target.shift(manim.LEFT)
            self.play(*[manim.MoveToTarget(num) for num in num3])
        self.wait()

        self.play(manim.FadeIn(plus2), *[manim.FadeIn(num) for num in add2])
        self.wait()
        self.play(*[manim.FadeOut(num3[i]) for i in range(3)])
        num3[0] = manim.Integer(0).shift(4 * manim.LEFT + 3 * manim.UP)
        num3[1] = manim.Integer(0).shift(3 * manim.LEFT + 3 * manim.UP)
        num3[2] = manim.Integer(1).shift(2 * manim.LEFT + 3 * manim.UP)
        num3.insert(0, manim.Integer(1).shift(5 * manim.LEFT + 3 * manim.UP))
        self.play(*[manim.FadeIn(num3[i]) for i in range(4)],
                  manim.FadeOut(plus2),
                  *[manim.FadeOut(num) for num in add2])

        for num in num3:
            num.generate_target()
            num.target.shift(manim.LEFT)
        self.play(*[manim.MoveToTarget(num) for num in num3])
        self.wait()

        self.play(manim.FadeIn(plus), *[manim.FadeIn(num) for num in add1])
        self.play(manim.FadeOut(num3[5]),
                  manim.FadeOut(num3[6]),
                  manim.FadeOut(num3[8]))
        num3[5] = manim.Integer(1).shift(1 * manim.LEFT + 3 * manim.UP)
        num3[6] = manim.Integer(0).shift(0 * manim.LEFT + 3 * manim.UP)
        num3[8] = manim.Integer(0).shift(-2 * manim.LEFT + 3 * manim.UP)
        self.play(manim.FadeIn(num3[5]),
                  manim.FadeIn(num3[6]),
                  manim.FadeIn(num3[8]),
                  manim.FadeOut(plus),
                  *[manim.FadeOut(num) for num in add1])
        self.wait()

        self.play(*[manim.FadeOut(square) for square in squares],
                  *[manim.FadeOut(num) for num in num3],
                  manim.FadeOut(example3_text))

        ending = manim.Text("Example3就是转bcd码的完全版本了\n" \
                            "而且可以根据这个原理拓展到二进制转任意进制",
                            color=manim.PURPLE,
                            t2c={"任意进制": manim.RED})
        self.play(manim.Write(ending))
        self.wait(2)
        self.play(manim.FadeOut(ending))

        ending2 = manim.Text("可Example3真的有看上去这么简单直观吗?\n我没法给出一个严谨的证明\n但我也有一点成果",
                             color=manim.PURPLE,
                             t2c = {"简单直观": "red"})
        self.play(manim.Write(ending2))
        self.wait(2)
        self.play(manim.FadeOut(ending2))

        t1 = manim.Text("设").shift(manim.UP * 3 + manim.LEFT * 2.2)
        l1 = manim.MathTex("num = \\sum_{i=0}^{n} a_i10^i").shift(manim.UP * 3)
        t2 = manim.Text("设bcd(num)为将num转为bcd码后的数字大小", font_size=30).shift(manim.UP * 2)
        l2 = manim.MathTex("\\therefore bcd(num) = \\sum_{i=0}^{n} a_i16^i").shift(manim.UP * 1)
        l3 = manim.MathTex("\\therefore \\delta = \\sum_{i=0}^{n} b_i(16^i - 10^i)")
        l4 = manim.MathTex("\\because 16^i-10^i=6(16^{i-1}+16^{i-2}10^1+...+10^{i-1})") \
            .shift(manim.DOWN * 1.3)
        t3 = manim.Text("所以确实是和6有关的", font_size=30).shift(manim.DOWN * 2)
        self.play(*[manim.Write(n) for n in (t1, l1, t2, l2, l3, l4, t3)])

        self.wait(3)

class Test(manim.Scene):
    def construct(self):
        t1 = manim.Text("设").shift(manim.UP * 3 + manim.LEFT * 2.2)
        l1 = manim.MathTex("num = \\sum_{i=0}^{n} a_i10^i").shift(manim.UP * 3)
        t2 = manim.Text("设bcd(num)为将num转为bcd码后的数字大小", font_size=30).shift(manim.UP * 2)
        l2 = manim.MathTex("\\therefore bcd(num) = \\sum_{i=0}^{n} a_i16^i").shift(manim.UP * 1)
        l3 = manim.MathTex("\\therefore \\delta = \\sum_{i=0}^{n} b_i(16^i - 10^i)")
        l4 = manim.MathTex("\\because 16^i-10^i=6(16^{i-1}+16^{i-2}10^1+...+10^{i-1})") \
            .shift(manim.DOWN * 1.3)
        t3 = manim.Text("所以确实是和6有关的", font_size=30).shift(manim.DOWN * 2)
        self.play(*[manim.Write(n) for n in (t1, l1, t2, l2, l3, l4, t3)])

if __name__ == "__main__":
    try:
        os.system("manim -p code/main.py Main")
    except KeyboardInterrupt:
        pass